
/**
 * @brief 对 <stdio.h> 重注入
 */
int putchar(int c)
{
    void _putchar(char character);
    _putchar(c);
    return c;
}

#define SYS_LOG_DOMAIN "main"
#include "sys_log.h"

#include "drivers/chip/_hal.h"

#if defined(__CC_ARM)

#define __HEAP_START __initial_sp
#define __HEAP_END (__initial_sp + 0x8000)
#define __STACK_SIZE 0

extern u8_t __initial_sp[];

#elif defined(__GNUC__) /* #if defined(__CC_ARM) */

#define __HEAP_START (__bss_end__ + (int)_Min_Heap_Size)
#define __HEAP_END _estack
#define __STACK_SIZE 0x400

extern u8_t _Min_Heap_Size[];
extern u8_t __bss_end__[];
extern u8_t _estack[];

#else /* #elif defined(__GNUC__) */

#endif

#if defined(MIX_COMMON)
#include <stdlib.h>
#include "heap/heap.h"
void _default_heap_init(void)
{
    heap_init(NULL, __HEAP_START, (uint)__HEAP_END - (uint)__HEAP_START - __STACK_SIZE);
}
#endif

#if defined(MIX_OS)

#include "os/os.h"

__weak int main(void)
{
    drv_hal_init();

#if defined(MIX_COMMON) && defined(MIX_RTK)
    const int size = heap_block_max(NULL);
#else
    const int size = (uint)__HEAP_END - (uint)__HEAP_START - __STACK_SIZE - 0x400;
#endif
    return os_start(__HEAP_START, size);
}

#elif defined(MIX_RTK)

#include "rtk.h"

__weak int main(void)
{
    drv_hal_init();

#if defined(MIX_COMMON)
    const int size = heap_block_max(NULL);
#else
    const int size = (uint)__HEAP_END - (uint)__HEAP_START - __STACK_SIZE - 0x400;
#endif
    return rtk_entry(malloc(size), size);
}

#elif defined(MIX_K_KIT)

#include "kk.h"

#ifndef CONFIG_MAX_SYSCALL_INTERRUPT_PRIORITY
#define CONFIG_MAX_SYSCALL_INTERRUPT_PRIORITY (0x8) /* 屏蔽的中断等级大于等于 8 */
#endif

static volatile unsigned _tick_counter = 0;

void SysTick_Handler(void)
{
    _tick_counter++;
}

static unsigned _port_get_sys_time(void)
{
    return _tick_counter;
}

static unsigned int _port_interrupt_save(void)
{
    uint32_t ulNewBASEPRI;

    __asm volatile(
        "	mov %0, %1												\n"
        "	msr basepri, %0											\n"
        "	isb														\n"
        "	dsb														\n"
        : "=r"(ulNewBASEPRI) : "i"(CONFIG_MAX_SYSCALL_INTERRUPT_PRIORITY << 4) : "memory");

    return 0;
}

static void _port_interrupt_restore(unsigned nest)
{
    __asm volatile(
        "	msr basepri, %0	" ::"r"(nest) : "memory");
}

__weak int main(void)
{
    drv_hal_init();

    drv_tick_enable(1000);

#if defined(MIX_COMMON)
    _default_heap_init();
#endif

    static k_init_t const init_struct = {
        .malloc = __malloc,
        .free = __free,
        .get_sys_ticks = _port_get_sys_time,
        .interrupt_save = _port_interrupt_save,
        .interrupt_restore = _port_interrupt_restore,

        .scheduler_disable = NULL,
        .scheduler_enable = NULL,
        .get_work_q_hdl = NULL,
        .thread_sleep = NULL,
    };
    k_entry(&init_struct);

    return 0;
}

#else

#include <stdlib.h>

__weak void SysTick_Handler(void)
{
}

__weak int app_main(void)
{
    SYS_LOG_ERR("no app to run");
    return -1;
}

__weak int main(void)
{
    drv_hal_init();

#if defined(MIX_COMMON)
    _default_heap_init();

    extern int none_entry(void);
    none_entry();
#else
    app_main();
#endif

    return 0;
}

#endif

void entry(void)
{
    main();
}

/* syscall ------------------------------------------------------------------------- */

#include "board_config.h"

__weak hal_uart_hdl_t const g_board_uart_cons;
static const hal_uart_hdl_t *s_console_id = &g_board_uart_cons;

/**
 * @brief initializes the UART emulated hardware
 */
__weak void SystemInit()
{
}

__weak int drv_uart_poll_write(hal_id_t id, uint8_t data)
{
    return 0;
}

__weak bool drv_uart_wait_tx_busy(hal_id_t id)
{
    return 0;
}

static void _console_poll_write(char c)
{
    drv_uart_poll_write(s_console_id->id, c);
    drv_uart_wait_tx_busy(s_console_id->id);
}

#if defined(__CC_ARM)

#pragma import(__use_no_semihosting)

struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};

/* FILE is typedef’ d in stdio.h. */
FILE __stdout;

void _sys_exit(int x)
{
    x = x;
}

// 重定向fputc函数
int fputc(int ch, FILE *f)
{
    _console_poll_write(ch);
    return (int)f;
}

#undef putchar

#elif defined(__GNUC__) /* #if defined ( __CC_ARM ) */

__weak int drv_uart_fifo_fill(hal_id_t id, const void *data, int size)
{
    return size;
}

static unsigned _console_fifo_fill(const void *data, int size)
{
    return drv_uart_fifo_fill(s_console_id->id, data, size);
}

int _write(int fd, char *pBuffer, int size)
{
    return _console_fifo_fill(pBuffer, size);
}

#endif /* #elif defined ( __GNUC__ ) */

/**
 * @brief 对 printf.h 兼容
 */
__weak void _putchar(char character)
{
    _console_poll_write(character);
}
